package jaux.tank.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;

import jaux.tank.bean.vo.node.TreeNode;

/**
 * 转换对象列表为树工具类.
 *
 *  
 */
public class TreeUtils {

	/**
	 * 生成树.
	 *
	 * @param <T> 对象类型
	 * @param objs 对象列表
	 * @param rootId 跟节点id
	 * @param getID 对象id映射
	 * @param getName 对象名称映射
	 * @param getParent 获取父对象
	 * @param getNo 获取顺序
	 * @return 树节点列表
	 */
	public static <T> List<TreeNode<T>> generateTree(List<T> objs, String rootId, GetId<T> getID, GetName<T> getName,
			GetPid<T> getParent, GetNo<T> getNo) {
		List<TreeNode<T>> nodeList = objs.stream().filter(obj -> {
			String pid = getParent.get(obj);
			if (rootId == null)
				return pid == null;
			return pid != null && rootId.equals(pid);
		}).map(obj -> {
			TreeNode<T> node = new TreeNode<T>();
			node.setId(getID.get(obj));
			node.setName(getName.get(obj));
			node.setNo(getNo.get(obj));
			node.setPid(rootId);
			node.setData(obj);
			return node;
		}).collect(Collectors.toList());
		nodeList.sort((a, b) -> a.getNo() - b.getNo());
		for (int i = 0; i < nodeList.size(); i++) {
			TreeNode<T> node = nodeList.get(i);
			List<TreeNode<T>> children = generateTree(objs, node.getId(), getID, getName, getParent, getNo);
			node.setChildren(children);
			node.setLeaf(CollectionUtils.isEmpty(children));
		}
		return nodeList;
	}
	/**
	 * 生成树节点列表(扁平的).
	 *
	 * @param <T> 对象类型
	 * @param objs 对象列表
	 * @param rootId 跟节点id
	 * @param getID 对象id映射
	 * @param getName 对象名称映射
	 * @param getParent 获取父对象
	 * @param getNo 获取顺序
	 * @return 树节点列表
	 */
	public static <T> List<TreeNode<T>> generateFlatTree(List<T> objs, String rootId, GetId<T> getID, GetName<T> getName,
			GetPid<T> getParent, GetNo<T> getNo) {
		List<TreeNode<T>> flatTreeNodeList = new ArrayList<TreeNode<T>>();
		List<TreeNode<T>> nodeList = objs.stream().filter(obj -> {
			String pid = getParent.get(obj);
			if (rootId == null)
				return pid == null;
			return pid != null && rootId.equals(pid);
		}).map(obj -> {
			TreeNode<T> node = new TreeNode<T>();
			node.setId(getID.get(obj));
			node.setName(getName.get(obj));
			node.setNo(getNo.get(obj));
			node.setPid(rootId);
			node.setData(obj);
			return node;
		}).collect(Collectors.toList());
		nodeList.sort((a, b) -> a.getNo() - b.getNo());
		flatTreeNodeList.addAll(nodeList);
		for (int i = 0; i < nodeList.size(); i++) {
			TreeNode<T> node = nodeList.get(i);
			List<TreeNode<T>> children = generateFlatTree(objs, node.getId(), getID, getName, getParent, getNo);
			flatTreeNodeList.addAll(children);
			node.setLeaf(CollectionUtils.isEmpty(children));
		}
		return flatTreeNodeList;
	}

	public interface GetId<T> {
		public   String get(T obj);
	}

	public interface GetName<T> {
		public   String get(T obj);
	}

	public interface GetNo<T> {
		public   int get(T obj);
	}

	public interface GetPid<T> {
		public  String get(T obj);
	}
}
